package com.apache.passport.common;

import com.apache.cache.util.Validator;
import com.apache.tools.ConfigUtil;
import com.apache.tools.MD5Utils;
import com.apache.tools.StrUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * description:  公共操作类
 *
 * @author Hou Dayu 创建时间：2016-12-18
 */
public class PassportHelper {

    private String filePath = "/config/unity_config.properties";

    private PassportHelper() {
        COOKIENAME = StrUtil
                .doNull(ConfigUtil.getInstance().getValueByKey("cookieName"), "apache_");
    }

    private String COOKIENAME = "";

    private static PassportHelper instance;

    private final Pattern pattern = Pattern.compile("\\S*[?]\\S*");//正则表达式

    //单例操作
    public static PassportHelper getInstance() {
        if (instance == null) {
            instance = new PassportHelper();
        }
        return instance;
    }

    /**
     * description:  获取连接后缀,只支持a.a不支持a.a.a
     *
     * @param url
     * @return
     */
    public String parseSuffix(String url) {
        if (url.length() <= 1) {
            return "";
        }
        Matcher matcher = pattern.matcher(url);

        String[] spUrl = url.toString().split("/");
        int len = spUrl.length;
        String endUrl = spUrl[len - 1];

        if (matcher.find()) {
            String[] spEndUrl = endUrl.split("\\?");
            return spEndUrl[0].split("\\.")[1];
        }
        return endUrl.split("\\.")[1];
    }

    /**
     * description:  支持全部url,webservice
     *
     * @param url
     * @return
     */
    public String parseUrlSuffix(String url) {
        int lastIndex = 0;
        String rtn = "";
        if (url.length() <= 1) {
            return rtn;
        }
        if (url.contains(".")) {
            lastIndex = url.lastIndexOf('.') + 1;
            return url.substring(lastIndex, url.length());
        }
        if (url.contains("@")) {
            lastIndex = url.lastIndexOf('@') + 1;
            return url.substring(lastIndex, url.length());
        }
        if (url.contains("#")) {
            lastIndex = url.lastIndexOf('#') + 1;
            return url.substring(lastIndex, url.length());
        }
        if (url.contains("?")) {
            lastIndex = url.lastIndexOf('?') + 1;
            return url.substring(lastIndex, url.length());
        }
        if (url.contains("!")) {
            lastIndex = url.lastIndexOf('!') + 1;
            String value = url.substring(lastIndex, url.length());
            if (value.contains(".")) {
                rtn = value.substring(value.indexOf('.'), value.length());
                return rtn;
            }
        }
        return url.substring(lastIndex, url.length());
    }

    /**
     * description:  获取登录用户IP地址
     *
     * @param request
     * @return
     */
    public String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.equals("0:0:0:0:0:0:0:1")) {
            ip = "127.0.0.1";
        }
        if(StrUtil.isNotNull(ip) && ip.indexOf(",")>=0){
            String[] str = ip.split(",");
            return str[0];
        }
        return ip;
    }

    /**
     * description:  获取当前登录用户的cookie值
     *
     * @param request
     * @return
     */
    public String getCurrCookie(HttpServletRequest request) {
        Cookie tokenCook = null;
        Cookie[] cookies = request.getCookies();
        if (null != cookies)
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(COOKIENAME)) {
                    tokenCook = cookie;
                    break;
                }
            }
        String result ="";
        if (tokenCook != null) {
            result = tokenCook.getValue();
        }
        return StrUtil.doNull(result,request.getHeader("zuultokenid"));
    }

    public String getTokenId(HttpServletRequest request) {
        String tokenId = PassportHelper.getInstance().getCurrCookie(request);
        if(StrUtil.isNull(tokenId)){
            String pkt = request.getParameter("tokenId");
            if ("undefined".equalsIgnoreCase(pkt))
                pkt = "";
            tokenId = StrUtil.doNull(tokenId,pkt);
        }
        return tokenId;
    }

    /**
     * description: 根据key获取cookie值
     *
     * @param request
     * @return
     */
    public String getCurrCookie(HttpServletRequest request, String key) {
        Cookie tokenCook = null;
        Cookie[] cookies = request.getCookies();
        if (null != cookies)
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(key)) {
                    tokenCook = cookie;
                    break;
                }
            }
        if (tokenCook == null) {
            return "";
        }
        return tokenCook.getValue();
    }

    /**
     * description:  获取url路径 必须为 req.getServletPath()后的路径
     *
     * @return
     */
    public String parseUrlPath(String servletpath) {
        if (servletpath.length() <= 1) {
            return "";
        }
        int lastIndex = servletpath.lastIndexOf('/');
        String urlpath = servletpath.substring(0, lastIndex + 1);
        return urlpath;
    }

    /**
     * 获取国际化信息
     *
     * @param msgKey key message_*.properties文件中的key
     * @param params key中{0}、{1}等对应的值
     * @param defaultMessage 对应的默认值
     * @return 返回对应的国际化信息
     */
    public String getMessage(HttpServletRequest request, String msgKey, String[] params,
            String defaultMessage) {
        WebApplicationContext requestContext = RequestContextUtils.findWebApplicationContext(request);
                //.getWebApplicationContext(request);
        Locale myLocale = RequestContextUtils.getLocale(request);
        String msg = requestContext.getMessage(msgKey, params, defaultMessage, myLocale);
        return Validator.getDefaultStr(msg, defaultMessage);
    }

    private Random random = new Random();

    private char ch[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
            'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
            'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1' };

    /**
     * description:  生成指定长度的随机字符串
     *
     * @param length
     * @return
     */
    public String createRandomString(int length) {
        if (length > 0) {
            int index = 0;
            char[] temp = new char[length];
            int num = random.nextInt();
            for (int i = 0; i < length % 5; i++) {
                temp[index++] = ch[num & 63];
                num >>= 6;
            }
            for (int i = 0; i < length / 5; i++) {
                num = random.nextInt();
                for (int j = 0; j < 5; j++) {
                    temp[index++] = ch[num & 63];
                    num >>= 6;
                }
            }
            return new String(temp, 0, length);
        } else if (length == 0) {
            return "";
        } else {
            throw new IllegalArgumentException();
        }
    }

    /**
     * description:  获取系统当前时间(yyyy-MM-dd HH:mm:ss)
     *
     * @return
     */
    public String sysNowDate() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    /**
     * description:  获取系统当前时间
     *
     * @param format 自定义日期格式 例如 format=yyyy-MM-dd HH:mm:ss
     * @return
     */
    public String sysNowDate(String format) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * description:  获取当前时间串
     *
     * @return
     */
    public long sysNowDateTypeInt() {
        Date date = new Date();
        return date.getTime();
    }

    /**
     * description:  sha1加密
     *
     * @param decript
     * @return
     */
    public String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte[] messageDigest = digest.digest();

            StringBuilder hexString = new StringBuilder();

            for (int i = 0; i < messageDigest.length; ++i) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * description:  直接使用对list内容进行sha1加密
     *
     * @param lst
     * @return
     */
    public String SHA1(ArrayList<String> lst) {
        try {
            Collections.sort(lst);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < lst.size(); ++i) {
                sb.append((String) lst.get(i));
            }
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(sb.toString().getBytes());
            byte[] messageDigest = digest.digest();

            StringBuilder hexString = new StringBuilder();

            for (int i = 0; i < messageDigest.length; ++i) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * description:  验证邮箱格式
     *
     * @param email
     * @return
     */
    public boolean emailFormat(String email) {
        Pattern p = Pattern.compile(
                "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$");
        Matcher m = p.matcher(email);
        return m.matches();
    }

    /***
     * description:  验证手机号格式
     * @param mobile
     * @return
     * @author Hou Dayu
     * @update 2015-1-16
     */
    public boolean mobileFormat(String mobile) {
        Pattern p = Pattern.compile("^13\\d{9}||18\\d{9}||15[1,2,3,5,8,9]\\d{8}$");
        Matcher m = p.matcher(mobile);
        return m.matches();
    }

    /**
     * description:  获取当前操作系统
     *
     * @return w:windows, m:mac,u:unix/linux,s:solaris
     */
    public String getSysOs() {
        String os = System.getProperty("os.name");
        if (os.contains("Win")) {
            return "w";
        }
        if (os.contains("Mac")) {
            return "m";
        }
        if (os.contains("Unix")) {
            return "u";
        }
        if (os.contains("Linux")) {
            return "u";
        }
        if (os.contains("solaris")) {
            return "s";
        }
        return os;
    }

    /**
     * description:  判断url地址是否正常
     *
     * @param scanStr url地址
     * @return true:url地址 false:非url地址
     */
    public boolean isDomain(String scanStr) {
        Pattern pattern = Pattern.compile(
                "^(http|https|ftp)\\://([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&amp;%\\$\\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\\:[0-9]+)*(/($|[a-zA-Z0-9\\.\\,\\?\\'\\\\+&amp;%\\$#\\=~_\\-]+))*$");
        Matcher matcher = pattern.matcher(scanStr);
        return matcher.find();
    }

    /**
     * description:  MD5加强版加密
     *
     * @param md5Str 明文
     * @return 返回MD5二次加密
     */
    public String getMd52(String md5Str) {
        return MD5Utils.MD5(MD5Utils.MD5(md5Str) + "iussoft");
    }

    /**
     * description:  将数据流转换成成string
     *
     * @param is
     * @return
     */
    public String InputStreamToString(InputStream is) {
        BufferedReader reader = null;
        StringBuilder responseText = null;
        String readerText = null;
        try {
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            responseText = new StringBuilder();
            readerText = reader.readLine();
            while (readerText != null) {
                responseText.append(readerText);
                responseText.append(System.getProperty("line.separator"));
                readerText = reader.readLine();
            }
            return responseText.toString();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(reader);
        }
        return "";
    }

    /**
     * description:  获取request中所有的参数数据,获取格式为:
     * <br>b1=1|b3=3|b2=2|b4=4
     * <br>多用于url跳转时,携带数据参数,且通过URLEncoder进行编码设置,编码格式为UTF-8
     * <br>url合成格式通过外部url进行确定,例如:
     * <br>http://localhost:8083/passport/test/test.action?b1=1|b3=3|b2=2|b4=4
     * <br>或者
     * <br>http://localhost:8083/passport/test/test.action?check=T|b1=1|b3=3|b2=2|b4=4
     * <br>需要确定的是?与&的使用,需要外部自行处理
     *
     * @param request
     * @return 参数字符串
     */
    public String getReqParams(HttpServletRequest request) {
        StringBuilder data = new StringBuilder();
        String dataParams = "";
        try {
            Map<String, String[]> map = request.getParameterMap();
            Set<Entry<String, String[]>> set = map.entrySet();
            Iterator<Entry<String, String[]>> it = set.iterator();

            while (it.hasNext()) {
                Entry<String, String[]> entry = it.next();
                String[] arr = entry.getValue();
                for (String i : arr) {
                    data.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                    data.append("=");
                    data.append(URLEncoder.encode(i, "UTF-8"));
                    data.append("|");
                }
            }
            if (!"".equals(data.toString())) {
                dataParams = data.substring(0, data.length() - 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataParams;
    }

    public String getReqParams(HttpServletRequest request, String filterStr) {
        StringBuilder data = new StringBuilder();
        String dataParams = "";
        try {
            Map<String, String[]> map = request.getParameterMap();
            Set<Entry<String, String[]>> set = map.entrySet();
            Iterator<Entry<String, String[]>> it = set.iterator();

            while (it.hasNext()) {
                Entry<String, String[]> entry = it.next();
                String ok = entry.getKey();
                if (filterStr.indexOf(ok) != -1) {
                    continue;
                }
                String[] arr = entry.getValue();
                for (String i : arr) {
                    data.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                    data.append("=");
                    data.append(URLEncoder.encode(i, "UTF-8"));
                    data.append("|");
                }
            }
            if (!"".equals(data.toString())) {
                dataParams = data.substring(0, data.length() - 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataParams;
    }

    /**
     * description:  如果data为空,则返回a,否则返回b
     *
     * @param data 字符串
     * @param a
     * @param b
     * @return
     */
    public String isNov(String data, String a, String b) {
        if (null == data || "".equals(data)) {
            return a;
        }
        return b;
    }

    ///监控请求白名单
    public static List<String> whiteJK= new ArrayList<String>() {{
        add("/health");
        add("/info");
        add("/auditevents");
        add("/metrics");
        add("/logfile");
        add("/loggers");
        add("/jolokia");
        add("/flyway");
        add("/liquibase");
        add("/dump");
        add("/heapdump");
        add("/auditevents");
        add("/env");
        add("/turbine");
        add("/trace");
        add("/hystrix");
        add("/api");
        add("/refresh");
        add("/offline");
        add("/online");
    }};
}
